import { px2Rem } from '@/utils/rem';
import { debounce } from 'lodash-es';
import { targetParent } from 'microconnect-common/utils/dom';
import { off, on } from 'microconnect-common/utils/event';
import { CSSProperties, defineComponent, PropType } from 'vue';
import './index.scss';

interface ISectionItem {
  label: string;
  children?: {
    label: string;
  }[];
}

const SECTION_ITEM_CLASS_NAME = 'section-item-title';
const SUB_SECTION_ITEM_CLASS_NAME = 'sub-section-item-title';

export const MciSectionWrap = defineComponent({
  name: 'MciSectionWrap',
  props: {
    /** 父级带滚动的选择器, document.querySelector支持的选择器 */
    scrollBy: {
      type: String,
      default: ''
    },
    mode: {
      type: String,
      default: ''
    },
    navWidth: {
      type: String,
      default: px2Rem('140px')
    },
    hiddenNav: {
      type: Boolean,
      default: false
    }
  },
  setup(props) {
    const navList = reactive<ISectionItem[]>([]);
    const els = ref({} as NodeListOf<Element> | undefined);
    const navContentRef = ref<HTMLDivElement>();
    let sectionOffsetTopList: number[] = [];
    let targetScroll: HTMLElement | null = null;
    let viewIndex = ref(0);
    const subSectionIndex = ref(0);
    let navTop = -1;

    const navStyles = computed(() => {
      if (!props.scrollBy) return {};
      return {
        top: 0,
        right: 0,
        position: 'sticky' as any,
        'max-height': 'calc(100vh - 200px)',
        'overflow-y': 'auto',
        'overflow-x': 'hidden'
      };
    });

    const addScrollEvent = () => {
      if (targetScroll) {
        on(targetScroll, 'scroll', contentScrollHandle as any);
      }
    };

    const removeScrollEvent = () => {
      if (targetScroll) {
        off(targetScroll, 'scroll', contentScrollHandle as any);
      }
    };

    // 用来区分是点击进行scroll的，停止scroll计算index
    let isClickScroll = false;

    const sectionItemClickHandle = (index: number) => {
      if (els.value?.length) {
        isClickScroll = true;
        els.value[index].scrollIntoView({ behavior: 'smooth', block: 'start' });
        viewIndex.value = index;
      }
    };

    const subSectionItemClickHandle = (index: number, subIndex: number) => {
      if (els.value?.length) {
        isClickScroll = true;
        const subItems = els.value[index]?.querySelectorAll(`.${SUB_SECTION_ITEM_CLASS_NAME}`);
        subItems[subIndex]?.scrollIntoView({ behavior: 'smooth', block: 'start' });
        viewIndex.value = index;
        subSectionIndex.value = subIndex;
      }
    };

    const resetOffsetTopList = debounce(() => {
      navTop = -1;
    }, 100);

    const getOffsetTopList = () => {
      sectionOffsetTopList = Array.from(els.value as unknown as HTMLDivElement[]).map((el) => {
        return el.getBoundingClientRect().top;
      });
    };

    const resetClickScroll = debounce(() => {
      isClickScroll = false;
    }, 100);

    const contentScrollHandle = (ev: UIEvent) => {
      resetClickScroll();
      if (isClickScroll) return;
      const target = ev.target as HTMLDivElement;
      if (navTop === -1) {
        navTop = target.getBoundingClientRect().top + 10;
      }

      getOffsetTopList();
      viewIndex.value = Math.max(sectionOffsetTopList.filter((val) => navTop > val).length - 1, 0);
      resetOffsetTopList();
    };

    onMounted(() => {
      if (props.scrollBy && navContentRef.value) {
        targetScroll = targetParent(navContentRef.value, props.scrollBy as any);
        addScrollEvent();
      }

      els.value = navContentRef.value?.querySelectorAll('.card-section-item');
      els.value?.forEach((el) => {
        const items = el.querySelectorAll(`.${SECTION_ITEM_CLASS_NAME}`);
        const subItems = el.querySelectorAll(`.${SUB_SECTION_ITEM_CLASS_NAME}`);
        const children: ISectionItem[] = [];
        subItems.forEach((subItem) => {
          children.push({
            label: subItem.innerHTML
          });
        });
        items.forEach((item) => {
          navList.push({
            label: (item.attributes as any)?.['alias-title']?.value || item?.innerHTML || '',
            children
          });
        });
      });
    });

    onUnmounted(removeScrollEvent);

    return {
      navList,
      viewIndex,
      subSectionIndex,
      sectionItemClickHandle,
      subSectionItemClickHandle,
      navContentRef,
      navStyles,
      contentScrollHandle
    };
  },
  render() {
    const { default: defaultSlot, navExtend: navExtendSlot, header: headerSlot } = this.$slots;
    const renderSectionNav = () => {
      if (this.hiddenNav || !this.scrollBy) return null;
      return (
        <div class={`mci-section-nav ml-12 mt-16`} style={{ width: this.navWidth }}>
          <div style={this.navStyles as any} class="mci-section-nav-content  overflow-y-auto">
            {this.navList.map((item, index) => {
              return (
                <>
                  <div
                    class={['mci-section-nav-item text-label-16 pl-12 mb-8', this.viewIndex === index && 'is-active']}
                    onClick={() => this.sectionItemClickHandle(index)}>
                    {item.label}
                  </div>
                  <div class="ml-20">
                    {item.children?.map((subItem, subIndex) => {
                      return (
                        <div
                          class={[
                            'mci-sub-section-nav-item text-label-16 cursor-pointer mb-8',
                            this.viewIndex === index && this.subSectionIndex === subIndex && 'is-sub-active'
                          ]}
                          onClick={() => this.subSectionItemClickHandle(index, subIndex)}>
                          {subItem.label}
                        </div>
                      );
                    })}
                  </div>
                </>
              );
            })}
            {navExtendSlot?.()}
          </div>
        </div>
      );
    };

    return (
      <div class="mci-section-wrap flex relative">
        <div ref="navContentRef" class="mci-section-wrap-content flex-1" onScroll={this.contentScrollHandle}>
          {headerSlot?.()}
          {defaultSlot?.()}
        </div>
        {renderSectionNav()}
      </div>
    );
  }
});

export const MciSectionItem = defineComponent({
  name: 'Section',
  props: {
    title: {
      type: String,
      default: ''
    },
    subTitle: {
      type: [String, Element, Object],
      default: ''
    },
    subTitleStyle: {
      type: Object as PropType<CSSProperties>,
      default: () => {}
    },
    description: {
      type: String,
      default: ''
    },
    aliasTitle: {
      type: [String],
      default: ''
    },
    isNav: {
      type: Boolean,
      default: true
    },
    // 卡片类型
    card: {
      type: Boolean,
      default: false
    }
  },
  emits: ['subEmit'],
  setup(_, { emit }) {
    const onSubEmit = () => {
      emit('subEmit');
    };

    return {
      onSubEmit
    };
  },
  render() {
    return (
      <div class="mci-section">
        <div class={['card-section-item', { 'rounded-8': this.card }]}>
          <div
            class={[
              'section-item flex items-center',
              this.card ? 'h-40 bg-green-6 cr-white px-16 rounded-t-8' : 'text-h3 mt-14 mb-16'
            ]}>
            {this.card ? <div class="w-4 h-20 bg-white opacity-64 mr-8"></div> : null}
            <div class={this.isNav ? `${SECTION_ITEM_CLASS_NAME}` : ''} alias-title={this.aliasTitle}>
              {this.title}
            </div>
            <div class="ml-16 sub-title text-label-14" style={this.subTitleStyle} onClick={this.onSubEmit}>
              {this.subTitle}
            </div>
          </div>
          <div class={{ 'bd p-16 rounded-b-8': this.card }}>
            {this.description && <div class="section-item text-value-16 my-16">{this.description}</div>}
            {this.$slots.default?.()}
          </div>
        </div>
      </div>
    );
  }
});

export const MciSubSectionItem = defineComponent({
  name: 'SubSectionItem',
  props: {
    title: {
      type: String,
      default: ''
    }
  },
  render() {
    return (
      <div class={['mci-sub-section-item']}>
        <div class={[SUB_SECTION_ITEM_CLASS_NAME]}>{this.title}</div>
        <div>{this.$slots.default?.()}</div>
      </div>
    );
  }
});
